﻿namespace Blaze.Framework.Pooling
{
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.Assertions;

    /// <summary>
    /// <see cref="GameObject"/>对象池管理器。
    /// </summary>
    [Singleton]
    public class GameObjectPoolManager : MonoBehaviour
    {
        /// <summary>
        /// 获取管理器的唯一实例。
        /// </summary>
        public static GameObjectPoolManager Instance
        {
            get
            {
                if (mInstance == null)
                    mInstance = Singleton.Get<GameObjectPoolManager>();
                return mInstance;
            }
        }

        /// <summary>
        /// 将指定编号的对象池清空。
        /// </summary>
        /// <param name="poolId">对象池编号</param>
        public void Clear(int poolId)
        {
            GameObjectPool pool;
            if (mPools.TryGetValue(poolId, out pool))
                pool.Clear();
        }

        /// <summary>
        /// 清空所有的对象池。
        /// </summary>
        public void ClearAll()
        {
            //TODO:清理所有的对象池
        }

        /// <summary>
        /// 初始化一个对象池。
        /// </summary>
        /// <param name="poolId">对象池编号</param>
        /// <param name="prefab">预设</param>
        /// <param name="initialSize">对象池初始大小</param>
        /// <param name="autoActive">对象池里的对象取出之后的 active 状态， 默认激活</param>
        public GameObjectPool Create(int poolId, Object prefab, int initialSize, bool autoActive = true)
        {
            Assert.IsNotNull(prefab);
            Assert.IsFalse(mPools.ContainsKey(poolId));
            var ret = new GameObjectPool(poolId, prefab, transform, initialSize, PoolInflationType.Increment, autoActive);
            mPools[poolId] = ret;
            return ret;
        }

        /// <summary>
        /// 删除指定的对象池。
        /// </summary>
        /// <param name="poolId">对象池编号</param>
        public void DeletePool(int poolId)
        {
            GameObjectPool pool;
            if (!mPools.TryGetValue(poolId, out pool))
                return;
            mPools.Remove(poolId);
            pool.Dispose();
        }

        /// <summary>
        /// 从指定的对象池中获取对象。
        /// </summary>
        /// <param name="poolId">池的编号</param>
        /// <returns>从池中获取的对象</returns>
        public GameObject Get(int poolId)
        {
            GameObjectPool pool;
            if (!mPools.TryGetValue(poolId, out pool))
                return null;
            var ret = pool.Get();
            return ret;
        }

        /// <summary>
        /// 获取指定的编号的对象池。
        /// </summary>
        /// <param name="poolId">对象池编号</param>
        public GameObjectPool GetPool(int poolId)
        {
            GameObjectPool pool;
            if (!mPools.TryGetValue(poolId, out pool))
                return null;
            return pool;
        }

        /// <summary>
        /// 将对象放入指定的池中。
        /// </summary>
        /// <param name="obj">需要放入的对象</param>
        public void Put(GameObject obj)
        {
            var po = obj.GetComponent<PoolObject>();
            Assert.IsNotNull(po, "Specified object is not a pooled instance: " + obj.name);

            GameObjectPool pool;
            if (mPools.TryGetValue(po.PoolId, out pool))
                pool.Put(po.gameObject);
            else
                Debug.LogWarning("No pool available with name: " + po.PoolId);
        }

        private readonly Dictionary<int, GameObjectPool> mPools = new Dictionary<int, GameObjectPool>();

        private static GameObjectPoolManager mInstance;
    }
}